package com.shuwen.gcdj.common.util.http;

import com.shuwen.gcdj.common.util.pojo.SignedHeader;
import com.shuwen.gcdj.common.util.tool.SecretTool;
import org.apache.http.Header;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriUtils;

import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

public class HttpUtil {
    private static final Logger log = LoggerFactory.getLogger(HttpUtil.class);
    private static final String ERROR_JSON = "{\"error\":{\"key\":\"global.service.internal.error\",\"message\":\"A server error has been encountered.\"}}";
    private static RestTemplate defaultTemplate;
    private static RestTemplate utf8Template;

    private HttpUtil() {
    }

    public static <T> ResponseEntity<String> exchange(String url, HttpMethod httpMethod, HttpEntity<T> httpEntity) {
        return exchange(defaultTemplate, url, httpMethod, httpEntity);
    }

    public static <T> ResponseEntity<String> exchange(RestTemplate restTemplate, String url, HttpMethod httpMethod, HttpEntity<T> httpEntity) {
        ResponseEntity result;
        try {
            result = restTemplate.exchange(url, httpMethod, httpEntity, String.class, new Object[0]);
        } catch (HttpClientErrorException var6) {
            log.debug("restTemplate.exchange() method:{} url:{} entity:{}", new Object[]{httpMethod.toString(), url, httpEntity.toString()});
            result = new ResponseEntity(var6.getResponseBodyAsString(), var6.getStatusCode());
        } catch (Exception var7) {
            result = new ResponseEntity("{\"error\":{\"key\":\"global.service.internal.error\",\"message\":\"A server error has been encountered.\"}}", HttpStatus.INTERNAL_SERVER_ERROR);
            log.error("restTemplate.exchange() method:{} url:{} entity:{} error:{}", new Object[]{httpMethod.toString(), url, httpEntity.toString(), var7.getMessage(), var7});
        }

        return result;
    }

    public static HttpHeaders getJsonHttpHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        return headers;
    }

    public static HttpHeaders getFormHttpHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        return headers;
    }

    public static HttpHeaders getXmlHttpHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.TEXT_XML);
        return headers;
    }

    public static HttpHeaders getSignedHeaders(String appkey, String secret) {
        SignedHeader header = getSignedHeader(appkey, secret);
        HttpHeaders headers = getJsonHttpHeaders();
        headers.add("appkey", appkey);
        headers.add("nonce", header.getNonce());
        headers.add("timestamp", header.getTimestamp());
        headers.add("signature", header.getSignature());
        return headers;
    }

    public static SignedHeader getSignedHeader(String appkey, String secret) {
        SecureRandom secureRandom = new SecureRandom();
        String nonce = String.valueOf((long)secureRandom.nextInt(1000000000) + 1000000000L);
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000L);
        String signature = SecretTool.generateSignature(appkey, secret, nonce, timestamp);
        return new SignedHeader(appkey, nonce, timestamp, signature);
    }

    public static String encodeAndJoinParams(Map<String, ?> uriParams) {
        Map<String, String> para = UriUtils.encodeUriVariables(uriParams);
        return (String)para.entrySet().stream().map((entity) -> {
            return (String)entity.getKey() + "=" + (String)entity.getValue();
        }).collect(Collectors.joining("&"));
    }

    public static RestTemplate getUtf8Template() {
        return utf8Template;
    }

    static {
        PoolingHttpClientConnectionManager pollingConnectionManager = new PoolingHttpClientConnectionManager(30L, TimeUnit.SECONDS);
        pollingConnectionManager.setMaxTotal(1000);
        pollingConnectionManager.setDefaultMaxPerRoute(1000);
        List<Header> headers = new ArrayList();
        headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36"));
        headers.add(new BasicHeader("Accept-Encoding", "gzip,deflate"));
        headers.add(new BasicHeader("Accept-Language", "zh-CN"));
        headers.add(new BasicHeader("Connection", "Keep-Alive"));
        HttpClient httpClient = HttpClients.custom().evictExpiredConnections().evictIdleConnections(60L, TimeUnit.SECONDS).setConnectionManager(pollingConnectionManager).setConnectionManagerShared(true).setRetryHandler(new DefaultHttpRequestRetryHandler(2, true)).setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy()).setDefaultHeaders(headers).build();
        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
        clientHttpRequestFactory.setConnectTimeout(5000);
        clientHttpRequestFactory.setReadTimeout(30000);
        clientHttpRequestFactory.setConnectionRequestTimeout(200);
        clientHttpRequestFactory.setBufferRequestBody(true);
        defaultTemplate = new RestTemplate(clientHttpRequestFactory);
        utf8Template = new RestTemplate(clientHttpRequestFactory);
        utf8Template.getMessageConverters().removeIf((converter) -> {
            return converter instanceof StringHttpMessageConverter;
        });
        utf8Template.getMessageConverters().add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
    }
}

